#include<stdio.h>
#include<Mesh_IO/Mesh_IO.h>
#include<tool/libcell_tools_io.h>
//#include<Mesh/Mesh_Frame.h>
#include<map>

#include<iterator/cstruct_iterator.h>
//#include<Mesh/lib_cell_Iterator.h>
#include<points_cloud_algorithm.h>
//#include<tool/tools_io.h>
#include<tools_node.h>
#define quote lib_cell_quote
#ifdef _MSC_VER
#ifdef __cplusplus
extern "C"{
#endif
__declspec(dllexport) int sum (int a,int b)
{

    return a+b;
}
__declspec(dllexport) Node* test_node(int n)
{
    Node* node=NULL;
    for(int i=0;i<n;i++)
    {
        //node=node_overlying(node,NULL);
       node=node_overlying(node,NULL); 
    }
    return node;
}
__declspec(dllexport) int Node_Size(Node * n)
{
   // return n;
    return node_size((Node*)n);
}
__declspec(dllexport) void test_denoising(char * file,char * filename)
{

    Mesh mesh;
    Mesh_init(&mesh);
    _Read_(&mesh,file);
   

    std::map<int,int> mp1;std::map<int,Node*> mp2;

    Mesh* mesh1=points_cloud_simplify_points_from_mesh(&mesh,10,mp1,mp2);

    printf("numv:%d\n",mesh1->num_v(mesh1) );
    Points_Cloud_Analyzer* pca=points_cloud_analyze_points_from_mesh(mesh1);
    // //printf("%lf\n",pca->median_distance );
    Node* node = points_cloud_classify_points_from_mesh(mesh1,1.5*pca->median_distance);
    points_cloud_analyzer_free(pca);

    printf("%d \n",node_size(node) );

    int size=0;double que=mesh1->num_v(mesh1)*2.0/100.0;
    for(Node* nit=node;nit!=NULL;nit=(Node*)(nit->Next))
    {
        size=node_size((Node*)(nit->value));
        if(size<que)
        {
            for(Node* nnit=(Node*)(nit->value);nnit!=NULL;nnit=(Node*)(nnit->Next))
            {
                template_v* v=(template_v*)(nnit->value);
                mesh1->delete_vertex(mesh1,*v,true);

            }
        }
        printf("%d %lf\n",size,que );
    }
    printf("%d %d\n",mesh1->num_v(mesh1),mp2.size() );
   // char filename[]="denoising.obj";
#ifdef _WIN32
    FILE *infile;
    fopen_s(&infile,filename,"w");
#else
    FILE *infile=fopen(filename,"w");
#endif 
    for(auto it=mesh1->v_begin(mesh1);it!=mesh1->v_end(mesh1);it++)
    {
        template_v* v=(template_v*)(quote(it)),*v1=NULL;
        Node* n=mp2[v->id];
        for(Node*nit=n;nit!=NULL;nit=(Node*)(nit->Next))
        {
            v=(template_v*)(nit->value);
            fprintf(infile, "v %lf %lf %lf\n",v->point[0],v->point[1],v->point[2] );
        }

    }
    fclose(infile);
    Mesh_free(mesh1);free(mesh1);Mesh_free(&mesh);
    for(Node* nit=node;nit!=NULL;nit=(Node*)(nit->Next))
    {
 	  free_node(((Node*)(nit->value)));
    }
    free_node(node);
    // nit=node;


    // Viewer_World_Manager* vwm=(Viewer_World_Manager*)malloc(sizeof(Viewer_World_Manager));
    // viewer_world_manager_init(vwm);
    // Viewer_World *vw=vwm->create_world(vwm,NULL);
    

    // Viewer_Opengl_Interpreter *voi=(Viewer_Opengl_Interpreter*)malloc(sizeof(Viewer_Opengl_Interpreter));
    // viewer_opengl_interpreter_initn(voi,vwm);

    
    // char points[]="Points";
    // Node* n=vw->create_something(vw,points);
    // auto vs=(Viewer_Something*)(n->value);
    // auto vp=(Viewer_Points*)(vs->evolution);
    // vp->Data_rows= mesh1->num_v(mesh1);

    // vp->pointsize=5.0;
    // vp->Data=(float*)malloc(sizeof(float)*3*vp->Data_rows);
    // int i=0;
    // for(auto vit=mesh1->vertices.begin();vit!=mesh1->vertices.end();vit++)
    // {
    //     vp->Data[i]=vit->second->point[0];
    //     i++;
    //     vp->Data[i]=vit->second->point[1];
    //     i++;
    //     vp->Data[i]=vit->second->point[2];
    //     i++;
    // }
    // float color[4]={0.9,0.2,0.5,1.0};
    // vp->set_color(vp,color);
    // set_default_voi(voi,vw);
    // voi->interpreter(voi);
}


#ifdef __cplusplus
}
#endif
#endif

